<?php

declare(strict_types=1);

namespace Plugin\Attractions\AttractionManagement\Service;

use App\Exception\BusinessException;
use App\Http\Common\ResultCode;
use App\Service\Wechat\MpService;
use Common\Common;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Plugin\Attractions\AttractionManagement\Repository\AttractionUserBookingRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionUserRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionUserTouristBookingRepository;
use Plugin\Attractions\AttractionManagement\Repository\AttractionUserTouristInfoRepository;

class UserService
{
    #[Inject]
    protected AttractionUserRepository $userRepository;

    #[Inject]
    protected AttractionUserTouristInfoRepository $touristInfoRepository;

    #[Inject]
    protected AttractionUserTouristBookingRepository $touristBookingRepository;

    #[Inject]
    protected AttractionUserBookingRepository $bookingRepository;

    #[Inject]
    private MpService $mpService;

    public function login(array $data)
    {
        try {
            $userInfo = $this->mpService->login($data);
        } catch (\Throwable $e) {
            Common::logException(__CLASS__, $e);
            throw new BusinessException(ResultCode::FAIL, trans('attraction-management.user.loginInfoError'));
        }
        // $userInfo = [
        //     'openid' => $data['code'],
        // ];
        // 检查用户是否存在
        $user = $this->userRepository->getQuery()
            ->where('open_id', $userInfo['openid'])
            ->where(function (Builder $query) {
                $query->whereNotNull('deleted_at')
                    ->orWhereNull('deleted_at');
            })
            ->first();
        // 创建用户
        if (!$user) {
            $userSuffix = intval(Common::redis()->get('attraction:user:user_suffix'));
            if (!$userSuffix) {
                Common::redis()->set('attraction:user:user_suffix', 1);
                $userSuffix = 1;
            }
            $user = $this->userRepository->create(
                [
                    'open_id' => $userInfo['openid'],
                    'username' => $userInfo['name'] ?? sprintf('游客_%06d', $userSuffix),
                    'avatar' => $userInfo['avatar'] ?? null,
                ]);
            Common::redis()->incr('user_suffix');
        } else if ($user->deleted_at) {
            // 恢复用户
            $user->restore();
            $user->update([
                'avatar' => $userInfo['avatar'], 
                'username' => $userInfo['name'],
                'times' => $user->times + 1,
            ]);
            // 恢复订单
            $this->bookingRepository->getModel()::withTrashed()
                ->where('user_id', $user->id)
                ->chunck(100, function ($bookings) {
                    $bookings->each(function ($booking) {
                        $booking->restore();
                    });
                });
            // 恢复游客
            $this->touristInfoRepository->getModel()::withTrashed()
                ->where('user_id', $user->id)
                ->chunck(100, function ($touristInfos) {
                    $touristInfos->each(function ($touristInfo) {
                        $touristInfo->restore();
                    });
                });
            // 恢复订单游客
            $this->touristBookingRepository->getModel()::withTrashed()
                ->where('user_id', $user->id)
                ->chunck(100, function ($touristBookings) {
                    $touristBookings->each(function ($touristBooking) {
                        $touristBooking->restore();
                    });
                });
        } else {
            $user->update(['times' => $user->times + 1]);
        }
        return Common::generateJwt(['id' => $user->id], 3600 * 8);
    }

    public function delete(array $id): bool
    {
        $ids = $this->userRepository->getQuery()->whereIn('id', $id)->pluck('id')->toArray();
        Db::beginTransaction();
        try {
            // 删除用户信息
            $this->userRepository->deleteById($ids);
            // 删除游客信息
            $this->touristInfoRepository->getQuery()->whereIn('user_id', $ids)->delete();
            // 删除用户预约信息
            $this->bookingRepository->deleteByUser($ids);
            Db::commit();
            return true;
        } catch (\Throwable $e) {
            Db::rollBack();
            Common::logException(__CLASS__, $e);
            return false;
        }
    }

    public function userInfo($params)
    {
        $user = $this->userRepository->findById($params['id']);
        if (!$user) {
            throw new BusinessException(ResultCode::NOT_FOUND);
        }
        return $user->toArray();
    }

    public function listUsers($params): array
    {
        return $this->userRepository->showListPage($params);
    }

    public function createTourist(array $data): array
    {
        // 检查用户是否存在
        $user = $this->userRepository->findById($data['userId']);
        if (!$user) {
            throw new BusinessException(ResultCode::NOT_FOUND, trans('attraction-management.user.notFound'));
        }

        // 创建游客信息
        $tourist = $this->touristInfoRepository->create([
            'user_id' => $user->id,
            'name' => $data['name'],
            'phone' => $data['phone'],
            'id_card' => $data['idCard'],
        ]);

        return $tourist->toArray();
    }

    public function deleteTourist(array $ids, int $userId): int
    {
        return $this->touristInfoRepository->getQuery()
            ->whereIn('id', $ids)
            ->where('user_id', $userId)
            ->delete();
    }

    public function updateTourist(array $ids, array $data, int $userId): int
    {
        if (isset($data['idCard'])) {
            $data['id_card'] = $data['idCard'];
        }
        return $this->touristInfoRepository->getQuery()
            ->whereIn('id', $ids)
            ->where('user_id', $userId)
            ->update($data);
    }

    public function listTourist($params): array
    {
        return $this->touristInfoRepository->list($params)->toArray();
    }
}
